/* 
 * 创建日期 2011-3-28
 *
 * 成都天和软件公司
 * 电话：028-85425861 
 * 传真：028-85425861-8008 
 * 邮编：610041 
 * 地址：成都市武侯区航空路6号丰德万瑞中心B座1001 
 * 版权所有
 */
package  org.fantasy.cpp.core.service.impl;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.json.JSONArray;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.entity.Entity;
import org.nutz.dao.sql.Sql;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import  org.fantasy.cpp.core.cache.ColumnDictCache;
import  org.fantasy.cpp.core.dao.nutz.BaseDAO;
import  org.fantasy.cpp.core.pojo.ChartConfig;
import  org.fantasy.cpp.core.pojo.QueryConfig;
import  org.fantasy.cpp.core.pojo.QueryItem;
import  org.fantasy.cpp.core.pojo.QueryModule;
import  org.fantasy.cpp.core.pojo.QueryPage;
import  org.fantasy.cpp.core.pojo.QueryTemplet;
import  org.fantasy.cpp.core.pojo.TableConfig;
import  org.fantasy.cpp.core.service.ConfigService;
import  org.fantasy.cpp.core.service.QueryService;
import  org.fantasy.common.cache.service.CacheService;
import  org.fantasy.common.compile.CompileCenter;
import  org.fantasy.common.db.bean.ColumnBean;
import  org.fantasy.common.db.bean.Row;
import  org.fantasy.common.grid.bean.Column;
import  org.fantasy.common.util.DateUtil;
import  org.fantasy.common.util.ParamMap;
import  org.fantasy.common.util.StringUtil;
import  org.fantasy.common.util.XMLUtil;

/**
 * 页面服务
 * 
 * @author: 王文成
 * @version: 1.0
 * @since 2011-3-11
 */
@Service("configService")
public class ConfigServiceImpl implements ConfigService {

	private static final Log log = LogFactory.getLog(ConfigServiceImpl.class);

	@Autowired
	private BaseDAO baseDAO;

	@Autowired
	private CompileCenter compileCenter;

	@Autowired
	@Qualifier("queryConfigCacheService")
	private CacheService cache;

	@Autowired
	private ColumnDictCache columnDictCache;

	@Autowired
	private QueryService queryService;
	
	public QueryPage getQueryPage(Long id) throws Exception {
		QueryPage page = baseDAO.fetch(QueryPage.class, id);
		return page;
	}

	public QueryPage saveQueryPage(ParamMap<String, Object> params) throws Exception {
		QueryPage bean = null;
		Long id = params.getLong("id");
		if (id == null) {
			bean = new QueryPage();
			BeanUtils.copyProperties(bean, params);
			bean.setState("A");
			bean.setCreateDate(DateUtil.getCurrentTimestamp());
			bean.setPageTypeId(QueryPage.PAGE_TYPE_NORMAL);
			baseDAO.insert(bean);
		} else {
			bean = baseDAO.fetch(QueryPage.class, id);
			BeanUtils.copyProperties(bean, params);
			baseDAO.update(bean);
		}
		String items = params.getString("items");
		// 保存查询条件
		if (!items.isEmpty()) {
			removeQueryPageItems(bean.getPageId());
			saveQueryPageItems(bean.getPageId(), items);
		}
		cache.clear();// 清除缓存
		return bean;
	}

	public void saveQueryPageItems(Long pageId, String items) throws Exception {
		JSONArray array = new JSONArray(items);
		for (int i = 0; i < array.length(); i++) {
			QueryModule module = new QueryModule();
			module.setItemId(array.getLong(i));
			module.setPageId(pageId);
			module.setSort(i);
			module.setState("A");
			baseDAO.insert(module);
		}
		cache.clear();// 清除缓存
	}

	@Override
	public void removeQueryPageItems(Long pageId) throws Exception {
		baseDAO.clear(QueryModule.class, Cnd.where("pageId", "=", pageId));
		cache.clear();// 清除缓存
	}

	@Override
	public void removeQueryPage(String id) throws Exception {
		QueryPage page = baseDAO.fetch(QueryPage.class, id);
		page.setState("X");
		baseDAO.update(page);
		cache.clear();// 清除缓存
	}

	@Override
	public QueryConfig saveQueryConfig(ParamMap<String, Object> params) throws Exception {
		QueryConfig bean = null;
		if (!params.isValid("id")) {
			bean = new QueryConfig();
			BeanUtils.copyProperties(bean, params);
			bean.setState("A");
			bean.setCreateDate(DateUtil.getCurrentTimestamp());
			baseDAO.insert(bean);
		} else {
			Long id = params.getLong("id");
			bean = baseDAO.fetch(QueryConfig.class, id);
			BeanUtils.copyProperties(bean, params);
			baseDAO.update(bean);
		}
		// 清空查询配置缓存
		compileCenter.reload(String.valueOf(bean.getQueryId()));
		cache.clear();// 清除缓存
		columnDictCache.clear();// 清除字典缓存
		return bean;
	}
	
	@Override
	public List<Row> executeQueryConfig(Long queryId, Map<String,Object> qryMap) throws Exception {
		return queryService.qryPageList(queryId, qryMap);
	}

	@Override
	public QueryConfig getQueryConfig(Long queryId) throws Exception {
		if (queryId != null){
			return baseDAO.fetch(QueryConfig.class, queryId);
		}
		return null;
	}

	@Override
	public TableConfig getTableConfig(Long tableId) throws Exception {
		if (tableId != null){
			return baseDAO.fetch(TableConfig.class, tableId);
		}
		return null;
	}

	@Override
	public TableConfig saveTableConfig(ParamMap<String, Object> params) throws Exception {
		TableConfig bean = null;
		if (!params.isValid("id")) {
			bean = new TableConfig();
			BeanUtils.copyProperties(bean, params);
			bean.setState("A");
			bean.setCreateDate(DateUtil.getCurrentTimestamp());
			baseDAO.insert(bean);
		} else {
			Long id = params.getLong("id");
			bean = baseDAO.fetch(TableConfig.class, id);
			BeanUtils.copyProperties(bean, params);
			baseDAO.update(bean);
		}
		cache.clear();// 清除缓存
		return bean;
	}

	@Override
	public ChartConfig getChartConfig(Long id) throws Exception {
		ChartConfig bean = baseDAO.fetch(ChartConfig.class, id);
		return bean;
	}

	@Override
	public ChartConfig saveChartConfig(ParamMap<String, Object> params) throws Exception {
		ChartConfig bean = null;
		if (!params.isValid("id")) {
			bean = new ChartConfig();
			BeanUtils.copyProperties(bean, params);
			bean.setState("A");
			bean.setCreateDate(DateUtil.getCurrentTimestamp());
			baseDAO.insert(bean);
		} else {
			Long id = params.getLong("id");
			bean = baseDAO.fetch(ChartConfig.class, id);
			BeanUtils.copyProperties(bean, params);
			baseDAO.update(bean);
		}
		cache.clear();// 清除缓存
		return bean;
	}

	@Override
	public QueryItem getQueryItem(Long id) throws Exception {
		QueryItem bean = baseDAO.fetch(QueryItem.class, id);
		return bean;
	}

	@Override
	public List<QueryItem> getSelectQueryItemList(Long pageId) throws Exception {
		StringBuilder query = new StringBuilder(512);
		query.append("select b.* from QUERY_MODULE a , QUERY_ITEM b  \n");
		query.append("where a.ITEM_ID = b.ITEM_ID  \n");
		query.append("and a.state='A' \n");
		query.append("and b.state='A' \n");
		query.append("and a.PAGE_ID = " + pageId + " \n");
		query.append("order by a.SORT \n");
		Sql sql = Sqls.create(query.toString());
		sql.setCallback(Sqls.callback.entities());
		Entity<QueryItem> entity = baseDAO.getEntity(QueryItem.class);
		sql.setEntity(entity).setCondition(Cnd.wrap("1=1"));
		baseDAO.execute(sql);
		return sql.getList(QueryItem.class);
	}

	@Override
	public List<QueryItem> getUnSelectQueryItemList(Long pageId) throws Exception {
		StringBuilder cnd = new StringBuilder(128);
		cnd.append("item_id not in(");
		cnd.append(" select item_id from QUERY_MODULE where page_id=" + pageId + " and state='A'");
		cnd.append(") and state='A'");
		return baseDAO.query(QueryItem.class, Cnd.wrap(cnd.toString()), null);
	}

	@Override
	public List<QueryItem> getQueryItemList() throws Exception {
		return baseDAO.query(QueryItem.class, Cnd.where("state", "=", "A"), null);
	}

	@Override
	public QueryItem saveQueryItem(ParamMap<String, Object> params) throws Exception {
		QueryItem bean = null;
		if (!params.isValid("id")) {
			bean = new QueryItem();
			BeanUtils.copyProperties(bean, params);
			bean.setState("A");
			baseDAO.insert(bean);
		} else {
			Long id = params.getLong("id");
			bean = baseDAO.fetch(QueryItem.class, id);
			BeanUtils.copyProperties(bean, params);
			baseDAO.update(bean);
		}
		cache.clear();// 清除缓存
		return bean;
	}

	@Override
	public void removeQueryItem(Long id) throws Exception {
		QueryItem bean = baseDAO.fetch(QueryItem.class, id);
		if (bean != null) {
			bean.setState("X");
			baseDAO.update(bean);
		}
		cache.clear();// 清除缓存
	}

	@Override
	public QueryTemplet getQueryTemplet(Long id) throws Exception {
		QueryTemplet bean = baseDAO.fetch(QueryTemplet.class, id);
		return bean;
	}

	@Override
	public QueryTemplet saveQueryTemplet(ParamMap<String, Object> params) throws Exception {
		QueryTemplet bean = null;
		if (!params.isValid("id")) {
			bean = new QueryTemplet();
			BeanUtils.copyProperties(bean, params);
			bean.setState("A");
			bean.setCreateDate(new Date());
			baseDAO.insert(bean);
		} else {
			Long id = params.getLong("id");
			bean = baseDAO.fetch(QueryTemplet.class, id);
			BeanUtils.copyProperties(bean, params);
			baseDAO.update(bean);
		}
		cache.clear();// 清除缓存
		return bean;
	}

	@Override
	public String guessTableConfig(Long queryId) throws Exception {
		StringBuilder xml = new StringBuilder(2048);
		try {
			if (queryId != null) {
				List<ColumnBean> rows = queryService.getColumns(queryId, new HashMap<String, Object>());
				for (ColumnBean col : rows) {
					xml.append(col.toColumnXml());
				}
			}
		} catch (Exception e) {
			log.error(e);
		}
		return xml.toString();
	}

	@Override
	@SuppressWarnings("unchecked")
	public String guessChartConfig(Long tableId) throws Exception {
		TableConfig bean = getTableConfig(tableId);
		String config = (bean != null ? bean.getTableConfig() : "");
		String name = (bean != null ? bean.getTableName() : "");
		StringBuilder chart = new StringBuilder(1024);
		chart.append("<chart caption='" + name + "'  id='Chart' type='Doughnut2D' css='width:100%;height:260px' ");
		chart.append("palette='6' baseFontSize='12' bgColor='FFFFFF' bgAlpha='100' showBorder='0'>\n");
		if (StringUtil.isValid(config)) {
			Document doc = getTableConfig(config);
			List<Element> elements = doc.selectNodes("//column");
			for (Element e : elements) {
				List<Element> attrList = XMLUtil.children(e, "attribute");
				Column column = getColumn(attrList);
				if (column.isNumberType() && !column.isID()) {
					chart.append("<set label='" + column.getFieldLabel() + "' value='#" + column.getFieldName() + "#' />\n");
				}
			}
		}
		chart.append("</chart>");
		return chart.toString();
	}

	/**
	 * 取得表格配置XML
	 * 
	 * @param config
	 * @return
	 */
	private Document getTableConfig(String config) {
		StringBuilder xml = new StringBuilder(2048);
		xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
		xml.append("<table>");
		xml.append(config);
		xml.append("</table>");
		try {
			Document doc = DocumentHelper.parseText(xml.toString());
			return doc;
		} catch (DocumentException e) {
			return DocumentHelper.createDocument();
		}
	}

	@SuppressWarnings("all")
	private Column getColumn(List<Element> attrList) throws Exception {
		Column column = new Column();
		Class cls = column.getClass();
		Class[] params = new Class[] { String.class };
		for (Element element : attrList) {
			String param = element.attributeValue("param");
			String value = element.getText();
			String methodName = "set" + StringUtil.firstCharUpperCase(param);
			Method method = cls.getMethod(methodName, params);
			method.invoke(column, value);
		}
		return column;
	}

	public static void main(String[] args) {
		System.out.println("QueryPage#19".equals("QueryPage#19"));
	}

}
